/*
    This file is part of Posixcpp library.

    Posixcpp library is free software: you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public License
    as published by the Free Software Foundation, either version 3 of
    the License, or (at your option) any later version.

    Posixcpp library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU LesserGeneral Public
    License along with Posixcpp library. If not, see
    <http://www.gnu.org/licenses/>.
*/

#ifndef POSIX_IO_HPP_INCLUDED
#define POSIX_IO_HPP_INCLUDED

#include <cstdlib>
#include <unistd.h>
#include <fcntl.h>
#include <poll.h>

#include "posixcpp.hpp"
#include "posixcpp_bytearray.hpp"
#include "posixcpp_flags.hpp"
#include "posix_time_timespec.hpp"

namespace posix {
/**
 * @namespace io
 * @brief Namspace for objects, envolved in the I/O process
 */
namespace io {
/**
 * @enum IOMode_t
 * @brief Read/Write mode
 */
enum class IOMode_t {
    /**
     * I/O operation returns like C single read/write, with the report of
     * actually received/transmitted bytes
	 */
	SINGLE,
    /**
	 * I/O operation make cycles, trying to receive/transmit requested data ammount
	 */
    LOOPED
};

/**
 * @enum AccessMode_t
 * @brief Node access mode
 */
enum class AccessMode_t {
    READ_ONLY = O_RDONLY,
    READ_WRITE = O_RDWR,
    WRITE_ONLY = O_WRONLY
};

POSIXCPP_FLAGS(Events, Events_t, short) {
    /**
     * Data ready to read
     */
    INPUT = POLLIN,
    /**
     * Data ready to write
     */
    OUTPUT = POLLOUT,
    /**
     * High priority data ready
     */
    URGENT = POLLPRI,
    /**
     * Error occured
     */
    ERROR = POLLERR,
    HANGUP = POLLHUP,
    /**
     * Invalid request
     */
    INVALID = POLLNVAL
};

POSIXCPP_FLAGS(Mode, Mode_t, unsigned int) {
    RWXU = S_IRWXU,
    RUSR = S_IRUSR,
    WUSR = S_IRUSR,
    XUSR = S_IXUSR,
    RWXG = S_IRWXG
};

enum class BlockingMode_t {
    BLOCK = 0,
    NON_BLOCK = O_NONBLOCK
};

/**
 * @interface IFile
 * @brief File operations interface
 */
class IHandle
{
public:
    virtual ~IHandle() {
    }
 
	/**
	 * @brief Close file
     */
    virtual void close() = 0;
	/**
	 * @brief Read data from file
     * @param data Byte array to read to, can be reduced in size to actual read count
     * @param mode Read mode ( single system call / looped untill the glorious end )
     * @param timeout poll timeout for looped mode
     */
    virtual void read(
      posixcpp::ByteArray & data,
      IOMode_t mode = IOMode_t::SINGLE,
      time::Timespec timeout = -1 ) = 0;
	/**
	 * @brief Write data to file
     * @param data Byte array to write from
     * @param mode Write mode ( single system call / looped untill the glorious end )
     * @param timeout poll timeout for looped mode
	 * @return actual read bytes
     */
    virtual ssize_t write(
      const posixcpp::ByteArray & data,
      IOMode_t mode = IOMode_t::LOOPED,
      time::Timespec timeout = -1 ) = 0;
	/**
	 * @brief Poll the device
     * @param events
     * @param timeout
     * @return Occured events mask
     */
    virtual Events poll(
      Events events,
      time::Timespec timeout = -1) = 0;
};

}
}

#endif // POSIX_IO_HPP_INCLUDED
